package br.com.hs.nfe.common.to;

import br.com.hs.nfe.AppUtil;
import br.com.hs.nfe.common.anotation.DocumentTypeEnum;
import br.com.hs.nfe.common.anotation.Element;
import br.com.hs.nfe.common.anotation.Node;
import br.com.hs.nfe.common.anotation.TypeEnum;
import br.com.hs.nfe.common.app.AppConfig;
import br.com.hs.nfe.common.exception.HSCommonException;
import br.com.hs.nfe.common.util.DocumentHelper;
import br.com.hs.nfe.common.util.HSConstants;
import br.com.hs.nfe.common.util.HSMessageConstants;
import br.com.hs.nfe.common.validation.Validable;
import br.com.hs.nfe.common.enumeration.FinalidadeEmissaoEnum;
import br.com.hs.nfe.common.enumeration.FormaPagamentoEnum;
import br.com.hs.nfe.common.enumeration.ProcessoEmissaoEnum;
import br.com.hs.nfe.common.enumeration.SituacaoNFeEnum;
import br.com.hs.nfe.common.enumeration.TipoAmbienteEnum;
import br.com.hs.nfe.common.enumeration.TipoEmissaoEnum;
import br.com.hs.nfe.common.enumeration.TipoImpressaoEnum;
import br.com.hs.nfe.common.enumeration.TipoOperacaoEnum;
import br.com.hs.nfe.common.util.ChaveAcessoHelper;
import br.inf.portalfiscal.nfe.TAmb;
import br.inf.portalfiscal.nfe.TCodUfIBGE;
import br.inf.portalfiscal.nfe.TFinNFe;
import br.inf.portalfiscal.nfe.TMod;
import br.inf.portalfiscal.nfe.TNFe;
import br.inf.portalfiscal.nfe.TProcEmi;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * Classe que representa a Nota Fiscal eletrônica -  NF-e.
 * @author Ranlive Hrysyk
 */
@Node(id = "B", name = "Nota Fiscal")
public class NotaFiscalTO extends BaseTO implements Validable {

    private String versao;
    @Element(elementName = "cUF", publicName = "Código da UF do Emitente", type = TypeEnum.ENUM, classType = TCodUfIBGE.Enum.class)
    private EmitenteTO emitenteTO;
    @Element(elementName = "cNF", publicName = "Código Numérico", type = TypeEnum.NUMBER, min = 8, max = 8)
    private String codigoNumericoChaveAcesso;
    @Element(elementName = "natOp", publicName = "Natureza da Operação", type = TypeEnum.CARACTER, min = 1, max = 60)
    private String naturezaOperacao;
    @Element(elementName = "indPag", publicName = "Indidcador Forma Pagamento", type = TypeEnum.ENUM, classType = TNFe.InfNFe.Ide.IndPag.Enum.class)
    private FormaPagamentoEnum formaPagamento;
    @Element(elementName = "mod", publicName = "Modelo", type = TypeEnum.ENUM, classType = TMod.Enum.class)
    private String modelo;
    @Element(elementName = "serie", publicName = "Série", type = TypeEnum.NUMBER, min = 1, max = 3)
    private String serie;
    @Element(elementName = "nNF", publicName = "Número Documento", type = TypeEnum.NUMBER, min = 1, max = 9)
    private String numero;
    @Element(elementName = "dEmi", publicName = "Data Emissão", type = TypeEnum.DATE, formart = "yyyy-MM-dd")
    private Date dataEmissao;
    @Element(elementName = "dSaiEnt", publicName = "Data Saída/Entrada", type = TypeEnum.DATE, formart = "yyyy-MM-dd", required = false)
    private Date dataSaidaEntrada;
    @Element(elementName = "hSaiEnt", publicName = "Hora Saída/Entrada", type = TypeEnum.DATE, formart = "HH:mm:ss", required = false)
    private Date horaSaidaEntrada;
    @Element(elementName = "tpNF", publicName = "Tipo de Operação", type = TypeEnum.ENUM, classType = TNFe.InfNFe.Ide.TpNF.Enum.class)
    private TipoOperacaoEnum tipoOperacao;
    @Element(elementName = "cMunFG", publicName = "Cód. Município Ocorrência", type = TypeEnum.NUMBER, min = 7, max = 7, document = DocumentTypeEnum.CMUN)
    private String codigoMunicipioFG;
    @Element(elementName = "tpImp", publicName = "Tipo Impressão DANFE", type = TypeEnum.ENUM, classType = TNFe.InfNFe.Ide.TpImp.Enum.class)
    private TipoImpressaoEnum tipoImpressao;
    @Element(elementName = "tpEmis", publicName = "Tipo Emissão NF-e", type = TypeEnum.ENUM, classType = TNFe.InfNFe.Ide.TpEmis.Enum.class)
    private TipoEmissaoEnum tipoEmissao;
    @Element(elementName = "cDV", publicName = "Dígito Verificador", type = TypeEnum.NUMBER, min = 1, max = 1)
    private String digitoVerificador;
    @Element(elementName = "tpAmb", publicName = "Identificação Ambiente", type = TypeEnum.ENUM, classType = TAmb.Enum.class)
    private TipoAmbienteEnum tipoAmbiente;
    @Element(elementName = "finNFe", publicName = "Finalidade Emissão NF-e", type = TypeEnum.ENUM, classType = TFinNFe.Enum.class)
    private FinalidadeEmissaoEnum finalidadeEmissao;
    @Element(elementName = "procEmi", publicName = "Processo Emissão NF-e", type = TypeEnum.ENUM, classType = TProcEmi.Enum.class)
    private ProcessoEmissaoEnum processoEmissao;
    @Element(elementName = "verProc", publicName = "Versão Processo Emissão NF-e", type = TypeEnum.CARACTER, min = 1, max = 20)
    private String versaoProcesso;
    @Element(elementName = "dhCont", publicName = "Data e Hora Entrada Contingência", type = TypeEnum.DATE, formart = "yyyy-MM-dd'T'HH:mm:ss", required = false)
    private Date dataHoraContigencia;
    @Element(elementName = "xJust", publicName = "Justificativa Entrada Contingência", type = TypeEnum.CARACTER, min = 15, max = 256, required = false)
    private String justificativa;
    private String xmlString;
    private ClienteTO clienteTO;
    private TransporteTO transporteTO;
    private List<ProdutoNotaTO> listaProdutos;
    private InfoTO infoTO;
    private SituacaoNFeEnum situacao;
    private LocalTO retirada;
    private LocalTO entrega;
    private String codigoErro;
    private String mensagemErro;

    /**
     * Inicia uma instância de NotaFiscalTO com o emitente registrado em AppUtil.
     * @throws HSCommonException Pode lançar uma exceção.
     */
    public NotaFiscalTO() throws HSCommonException {
        this(AppUtil.getEmitenteTO());
    }

    /**
     * Inicia uma instância de NotaFiscalTO informando um emitente. 
     * @param emitenteTO Emitente da Nota Fiscal.
     * @throws HSCommonException Pode lançar uma exceção.
     */
    public NotaFiscalTO(EmitenteTO emitenteTO) throws HSCommonException {
        this.versao = AppConfig.getInstance().getVersaoSchema();
        this.formaPagamento = FormaPagamentoEnum.A_VISTA;
        this.modelo = HSConstants.XML_MODELO_DOCUMENTO_FISCAL;
        this.dataEmissao = Calendar.getInstance().getTime();
        this.tipoOperacao = TipoOperacaoEnum.SAIDA;
        this.tipoImpressao = TipoImpressaoEnum.RETRATO;
        this.tipoEmissao = TipoEmissaoEnum.NORMAL;
        this.tipoAmbiente = TipoAmbienteEnum.getEnumByCodigo(AppConfig.getInstance().getTipoAmbiente());
        this.finalidadeEmissao = FinalidadeEmissaoEnum.NFE_NORMAL;
        this.processoEmissao = ProcessoEmissaoEnum.NFE_APLICATIVO_CONTRIBUINTE;
        this.versaoProcesso = AppConfig.getInstance().getVersaoAplicativo();
        this.situacao = SituacaoNFeEnum.EM_DIGITACAO;

        if (emitenteTO != null) {
            this.emitenteTO = emitenteTO;
        } else {
            throw new HSCommonException(HSMessageConstants.MSG_EMITENTE_NOT_NULL);
        }
        //Atualiza os dados do xml.
        updateXML();
    }

    /**
     * Inicializa/Atualiza o xml da nota fiscal.
     */
    private void updateXML() throws HSCommonException {
        DocumentHelper.updateXml(this);
    }

    /**
     * Calcula e obtém a chave de acesso da NF-e.
     */
    public String getChaveAcesso() {
        return ChaveAcessoHelper.gerarChaveAcesso(this);
    }

    /**
     * Versão do Leiaute da NF-e.
     */
    public String getVersao() {
        return versao;
    }

    /**
     * Informar a versão do leiaute da NF-e.
     * @param versao Versão do Leiaute da NF-e
     */
    public void setVersao(String versao) {
        this.versao = versao;
    }

    /**
     * Obtém o String do xml da Nota Fiscal.
     */
    public final String getXmlString() {
        return xmlString;
    }

    /**
     * Informar o String do xml da Nota Fiscal.
     * @param xmlString String do xml
     */
    public void setXmlString(String xmlString) {
        this.xmlString = xmlString;
    }

    /**
     * Emitente da NF-e.
     */
    public EmitenteTO getEmitenteTO() {
        return emitenteTO;
    }

    /**
     * Código da UF do emitente do documento fiscal.
     */
    public String getCUF() {
        return ((emitenteTO.getEnderEmit() != null) && (emitenteTO.getEnderEmit().getUFEnum() != null)) ? emitenteTO.getEnderEmit().getUFEnum().getCUF() : null;
    }

    /**
     * Código Numérico que Compõe a Chave de Acesso.
     */
    public String getCodigoNumericoChaveAcesso() {
        return codigoNumericoChaveAcesso;
    }

    /**
     * Código Numérico que Compõe a Chave de Acesso.
     */
    public String getCNF() {
        return getCodigoNumericoChaveAcesso();
    }

    /**
     * Informar o código numérico que compõe a chave de acesso.
     * @param codigoNumericoChaveAcesso Código Numérico que Compõe a Chave de Acesso
     */
    public final void setCodigoNumericoChaveAcesso(String codigoNumericoChaveAcesso) {
        this.codigoNumericoChaveAcesso = codigoNumericoChaveAcesso;
    }

    /**
     * Informar o código numérico que compõe a chave de acesso.
     * @param codigoNumericoChaveAcesso Código Numérico que Compõe a Chave de Acesso
     */
    public void setCNF(String codigoNumericoChaveAcesso) {
        setCodigoNumericoChaveAcesso(codigoNumericoChaveAcesso);
    }

    /**
     * Natureza da Operação. 
     */
    public String getNaturezaOperacao() {
        return naturezaOperacao;
    }

    /**
     * Natureza da Operação. 
     */
    public String getNatOp() {
        return getNaturezaOperacao();
    }

    /**
     * Informar a natureza da operação de que decorrer a saída ou a entrada, tais como: vensa, compra, transferência, 
     * devolução, importação, remessa (para fins de demonstração, de industrialização ou outra), 
     * conforme previsto na alínea 'i' inciso I, art. 19 do CONVÊNIO S/N°, de 15 de dezembro de 1970.
     * @param naturezaOperacao Natureza da Operação
     */
    public void setNaturezaOperacao(String naturezaOperacao) {
        this.naturezaOperacao = naturezaOperacao;
    }

    /**
     * Informar a natureza da operação de que decorrer a saída ou a entrada, tais como: vensa, compra, transferência, 
     * devolução, importação, remessa (para fins de demonstração, de industrialização ou outra), 
     * conforme previsto na alínea 'i' inciso I, art. 19 do CONVÊNIO S/N°, de 15 de dezembro de 1970.
     * @param naturezaOperacao Natureza da Operação
     */
    public void setNatOp(String naturezaOperacao) {
        setNaturezaOperacao(naturezaOperacao);
    }

    /**
     * Indicador da forma de pagamento.
     */
    public FormaPagamentoEnum getFormaPagamento() {
        return formaPagamento;
    }

    /**
     * Indicador da forma de pagamento.
     */
    public String getIndPag() {
        if (formaPagamento != null) {
            return formaPagamento.getCodigo();
        }
        return null;
    }

    /**
     * Informar o indicador da forma de pagamento.
     * @param formaPagamento Indicador da forma de pagamento
     */
    public void setFormaPagamento(FormaPagamentoEnum formaPagamento) {
        this.formaPagamento = formaPagamento;
    }

    /**
     * Informar o indicador da forma de pagamento.
     * <p>Este campo deverá ser obrigatoriamente preenchido com:
     * <br>0 - Pagamento à vista;
     * <br>1 - Pagamento à prazo;
     * <br>2 - Outros.
     * </p>
     * @param formaPagamento Indicador da forma de pagamento
     */
    public void setIndPag(String formaPagamento) {
        this.formaPagamento = FormaPagamentoEnum.getEnumByCodigo(formaPagamento);
    }

    /**
     * Código do Modelo do Documento Fiscal.
     */
    public String getModelo() {
        return modelo;
    }

    /**
     * Código do Modelo do Documento Fiscal.
     */
    public String getMod() {
        return getModelo();
    }

    /**
     * Informar o código do modelo do documento fiscal.
     * <p><i>Utilizar o código "55" para identificação da NF-e, emitida em substituição ao modelo 1 ou 1A</i></p>
     * @param modelo Código do Modelo do Documento Fiscal
     */
    public void setModelo(String modelo) {
        this.modelo = modelo;
    }

    /**
     * Informar o código do modelo do documento fiscal.
     * <p><i>Utilizar o código "55" para identificação da NF-e, emitida em substituição ao modelo 1 ou 1A</i></p>
     * @param modelo Código do Modelo do Documento Fiscal
     */
    public void setMod(String modelo) {
        setModelo(modelo);
    }

    /**
     * Série do Documento Fiscal.
     */
    public String getSerie() {
        return serie;
    }

    /**
     * Informar a série do documento fiscal.
     * <p>Preencher com zeros na hipótese de a NF-e não possuir série.
     * <br>Série 890-899 de uso exclusivo para emissão de NF-e avulsa, pelo contribuinte com seu certificado
     * digital, através do site do Fisco (procEmi=2).
     * <br>Série 900-999 de uso exclusivo de NF-e emitidas no SCAN.</p>
     * @param serie Série do Documento Fiscal
     */
    public void setSerie(String serie) {
        this.serie = serie;
    }

    /**
     * Número do Documento Fiscal.
     */
    public String getNumero() {
        return numero;
    }

    /**
     * Número do Documento Fiscal.
     */
    public String getNNF() {
        return getNumero();
    }

    /**
     * Informar o número do documento fiscal - Número da Nota.
     * @param numero Número do Documento Fiscal
     */
    public void setNumero(String numero) {
        this.numero = numero;
    }

    /**
     * Informar o número do documento fiscal - Número da Nota.
     * @param numero Número do Documento Fiscal
     */
    public void setNNF(String numero) {
        setNumero(numero);
    }

    /**
     * Data de Emissão.
     */
    public Date getDataEmissao() {
        return dataEmissao;
    }

    /**
     * Data de Emissão.
     */
    public Date getDEmi() {
        return getDataEmissao();
    }

    /**
     * Informar a data de emissão do documento fiscal.
     * <br>Formato: "AAAA-MM-DD"
     * @param dataEmissao Data de Emissão.
     */
    public void setDataEmissao(Date dataEmissao) {
        this.dataEmissao = dataEmissao;
    }

    /**
     * Informar a data de emissão do documento fiscal.
     * <br>Formato: "AAAA-MM-DD"
     * @param dataEmissao Data de Emissão.
     */
    public void setDEmi(Date dataEmissao) {
        setDataEmissao(dataEmissao);
    }

    /**
     * Data de Saída ou da Entrada.
     */
    public Date getDataSaidaEntrada() {
        return dataSaidaEntrada;
    }

    /**
     * Data de Saída ou da Entrada.
     */
    public Date getDSaiEnt() {
        return getDataSaidaEntrada();
    }

    /**
     * Informar a data de saída ou da entrada da mercadoria/produto.
     * <br>Formato: "AAAA-MM-DD"
     * @param dataSaidaEntrada Data de Saída ou da Entrada
     */
    public void setDataSaidaEntrada(Date dataSaidaEntrada) {
        this.dataSaidaEntrada = dataSaidaEntrada;
    }

    /**
     * Informar a data de saída ou da entrada da mercadoria/produto.
     * <br>Formato: "AAAA-MM-DD"
     * @param dataSaidaEntrada Data de Saída ou da Entrada
     */
    public void setDSaiEnt(Date dataSaidaEntrada) {
        setDataSaidaEntrada(dataSaidaEntrada);
    }

    /**
     * Hora de Saída ou da Entrada.
     */
    public Date getHoraSaidaEntrada() {
        return horaSaidaEntrada;
    }

    /**
     * Hora de Saída ou da Entrada.
     */
    public Date getHSaiEnt() {
        return getHoraSaidaEntrada();
    }

    /**
     * Informar a hora de saída ou da entrada da mercadoria/produto.
     * <br>Formato: "HH:MM:SS"
     * @param horaSaidaEntrada Hora de Saída ou da Entrada
     */
    public void setHoraSaidaEntrada(Date horaSaidaEntrada) {
        this.horaSaidaEntrada = horaSaidaEntrada;
    }

    /**
     * Informar a hora de saída ou da entrada da mercadoria/produto.
     * <br>Formato: "HH:MM:SS"
     * @param horaSaidaEntrada Hora de Saída ou da Entrada
     */
    public void setHSaiEnt(Date horaSaidaEntrada) {
        setHoraSaidaEntrada(horaSaidaEntrada);
    }

    /**
     * Tipo de Operação.
     */
    public TipoOperacaoEnum getTipoOperacao() {
        return tipoOperacao;
    }

    /**
     * Tipo de Operação.
     */
    public String getTpNF() {
        if (tipoOperacao != null) {
            return tipoOperacao.getCodigo();
        }
        return null;
    }

    /**
     * Informar o tipo de operação.
     * @param tipoOperacao Tipo de Operação
     */
    public void setTipoOperacao(TipoOperacaoEnum tipoOperacao) {
        this.tipoOperacao = tipoOperacao;
    }

    /**
     * Informar o tipo de operação.
     * <p>Este campo deverá ser obrigatoriamente preenchido com:
     * <br>0 - Entrada;
     * <br>1 - Saída.
     * </p>
     * @param tipoOperacao Tipo de Operação
     */
    public void setTpNF(String tipoOperacao) {
        this.tipoOperacao = TipoOperacaoEnum.getEnumByCodigo(tipoOperacao);
    }

    /**
     * Código do Município de Ocorrência.
     */
    public String getCodigoMunicipioFG() {
        return codigoMunicipioFG;
    }

    /**
     * Código do Município de Ocorrência.
     */
    public String getCMunFG() {
        return getCodigoMunicipioFG();
    }

    /**
     * Informar o código do município de ocorrência do fato gerador.
     * @param codigoMunicipioFG Código do Município de Ocorrência.
     */
    public void setCodigoMunicipioFG(String codigoMunicipioFG) {
        this.codigoMunicipioFG = codigoMunicipioFG;
    }

    /**
     * Informar o código do município de ocorrência do fato gerador.
     * @param codigoMunicipioFG Código do Município de Ocorrência.
     */
    public void setCMunFG(String codigoMunicipioFG) {
        setCodigoMunicipioFG(codigoMunicipioFG);
    }

    /**
     * Formato de impressão do DANFE.
     */
    public TipoImpressaoEnum getTipoImpressao() {
        return tipoImpressao;
    }

    /**
     * Formato de impressão do DANFE.
     */
    public String getTpImp() {
        if (tipoImpressao != null) {
            return tipoImpressao.getCodigo();
        }
        return null;
    }

    /**
     * Informar o tipo do formato de impressão do DANFE.
     * @param tipoImpressao Formato de impressão do DANFE
     */
    public void setTipoImpressao(TipoImpressaoEnum tipoImpressao) {
        this.tipoImpressao = tipoImpressao;
    }

    /**
     * Informar o tipo do formato de impressão do DANFE.
     * <p>Este campo deverá ser obrigatoriamente preenchido com:
     * <br>1 - Retrato;
     * <br>2 - Paisagem.
     * </p>
     * @param tipoImpressao Formato de impressão do DANFE
     */
    public void setTpImp(String tipoImpressao) {
        this.tipoImpressao = TipoImpressaoEnum.getEnumByCodigo(tipoImpressao);
    }

    /**
     * Tipo de Emissão da NF-e.
     */
    public TipoEmissaoEnum getTipoEmissao() {
        return tipoEmissao;
    }

    /**
     * Tipo de Emissão da NF-e.
     */
    public String getTpEmis() {
        if (tipoEmissao != null) {
            return tipoEmissao.getCodigo();
        }
        return null;
    }

    /**
     * Informar o tipo de emissão da NF-e.
     * @param tipoEmissao Tipo de Emissão da NF-e.
     */
    public void setTipoEmissao(TipoEmissaoEnum tipoEmissao) {
        this.tipoEmissao = tipoEmissao;
    }

    /**
     * Informar o tipo de emissão da NF-e.
     * <p>Este campo deverá ser obrigatoriamente preenchido com:
     * <br>1 - Normal;
     * <br>2 - Contingência;
     * <br>3 - Contingência com SCAN;
     * <br>4 - Contingência via DPEC;
     * <br>5 - Contingência FS-DA.
     * </p>
     * @param tipoEmissao Tipo de Emissão da NF-e.
     */
    public void setTpEmis(String tipoEmissao) {
        this.tipoEmissao = TipoEmissaoEnum.getEnumByCodigo(tipoEmissao);
    }

    /**
     * Dígito Verificador da Chave Acesso.
     */
    public String getDigitoVerificador() {
        return digitoVerificador;
    }

    /**
     * Dígito Verificador da Chave Acesso.
     */
    public String getCDV() {
        return getDigitoVerificador();
    }

    /**
     * Informar o dígito verificador da chave de acesso da NF-e.
     * @param digitoVerificador Dígito Verificador da Chave Acesso
     */
    public final void setDigitoVerificador(String digitoVerificador) {
        this.digitoVerificador = digitoVerificador;
    }

    /**
     * Informar o dígito verificador da chave de acesso da NF-e.
     * @param digitoVerificador Dígito Verificador da Chave Acesso
     */
    public void setCDV(String digitoVerificador) {
        setDigitoVerificador(digitoVerificador);
    }

    /**
     * Identificação do Ambiente.
     */
    public TipoAmbienteEnum getTipoAmbiente() {
        return tipoAmbiente;
    }

    /**
     * Identificação do Ambiente.
     */
    public String getTpAmb() {
        if (tipoAmbiente != null) {
            return tipoAmbiente.getCodigo();
        }
        return null;
    }

    /**
     * Informa a identificação do tipo de ambiente.
     * @param tipoAmbiente Identificação do Ambiente.
     */
    public void setTipoAmbiente(TipoAmbienteEnum tipoAmbiente) {
        this.tipoAmbiente = tipoAmbiente;
    }

    /**
     * Informa a identificação do tipo de ambiente.
     * <p>Este campo deverá ser obrigatoriamente preenchido com:
     * <br>1 - Produção;
     * <br>2 - Homologação.
     * </p>
     * @param tipoAmbiente Identificação do Ambiente.
     */
    public void setTpAmb(String tipoAmbiente) {
        this.tipoAmbiente = TipoAmbienteEnum.getEnumByCodigo(tipoAmbiente);
    }

    /**
     * Finalidade de Emissão da NF-e.
     */
    public FinalidadeEmissaoEnum getFinalidadeEmissao() {
        return finalidadeEmissao;
    }

    /**
     * Finalidade de Emissão da NF-e.
     */
    public String getFinNFe() {
        if (finalidadeEmissao != null) {
            return finalidadeEmissao.getCodigo();
        }
        return null;
    }

    /**
     * Informar a finalidade de emissão da NF-e.
     * @param finalidadeEmissao Finalidade de Emissão da NF-e
     */
    public void setFinalidadeEmissao(FinalidadeEmissaoEnum finalidadeEmissao) {
        this.finalidadeEmissao = finalidadeEmissao;
    }

    /**
     * Informar a finalidade de emissão da NF-e.
     * <p>Este campo deverá ser obrigatoriamente preenchido com:
     * <br>1 - NF-e normal;
     * <br>2 - NF-e complementar;
     * <br>3 - NF-e de ajuste.
     * </p>
     * @param finalidadeEmissao Finalidade de Emissão da NF-e
     */
    public void setFinNFe(String finalidadeEmissao) {
        this.finalidadeEmissao = FinalidadeEmissaoEnum.getEnumByCodigo(finalidadeEmissao);
    }

    /**
     * Processo de emissão da NF-e.
     */
    public ProcessoEmissaoEnum getProcessoEmissao() {
        return processoEmissao;
    }

    /**
     * Processo de emissão da NF-e.
     */
    public String getProcEmi() {
        if (processoEmissao != null) {
            return processoEmissao.getCodigo();
        }
        return null;
    }

    /**
     * Informar o identificador do processo de emissão da NF-e.
     * @param processoEmissao Processo de emissão da NF-e
     */
    public void setProcessoEmissao(ProcessoEmissaoEnum processoEmissao) {
        this.processoEmissao = processoEmissao;
    }

    /**
     * Informar o identificador do processo de emissão da NF-e.
     * <p>Este campo deverá ser obrigatoriamente preenchido com:
     * <br>0 - NF-e com aplicativo do contribuinte;
     * <br>1 - NF-e avulsa pelo Fisco;
     * <br>2 - NF-e avulsa pelo site do Fisco;
     * <br>3 - NF-e com aplicativo do Fisco.
     * </p>
     * @param processoEmissao Processo de emissão da NF-e
     */
    public void setProcEmi(String processoEmissao) {
        this.processoEmissao = ProcessoEmissaoEnum.getEnumByCodigo(processoEmissao);
    }

    /**
     * Versão do Processo Emissão da NF-e.
     */
    public String getVersaoProcesso() {
        return versaoProcesso;
    }

    /**
     * Versão do Processo Emissão da NF-e.
     */
    public String getVerProc() {
        return getVersaoProcesso();
    }

    /**
     * Informar a versão do aplicativo emissor de NF-e.
     * @param versaoProcesso Versão do Processo Emissão da NF-e
     */
    public void setVersaoProcesso(String versaoProcesso) {
        this.versaoProcesso = versaoProcesso;
    }

    /**
     * Informar a versão do aplicativo emissor de NF-e.
     * @param versaoProcesso Versão do Processo Emissão da NF-e
     */
    public void setVerProc(String versaoProcesso) {
        setVersaoProcesso(versaoProcesso);
    }

    /**
     * Data e Hora da Entrada em Contingência.
     */
    public Date getDataHoraContigencia() {
        return dataHoraContigencia;
    }

    /**
     * Data e Hora da Entrada em Contingência.
     */
    public Date getDhCont() {
        return getDataHoraContigencia();
    }

    /**
     * Informar a data e a hora da entrada em contingência.
     * <br>Formato: "AAAA-MM-DDTHH:MM:SS"
     * @param dataHoraContigencia Data e Hora da Entrada em Contingência.
     */
    public void setDataHoraContigencia(Date dataHoraContigencia) {
        this.dataHoraContigencia = dataHoraContigencia;
    }

    /**
     * Informar a data e a hora da entrada em contingência.
     * <br>Formato: "AAAA-MM-DDTHH:MM:SS"
     * @param dataHoraContigencia Data e Hora da Entrada em Contingência.
     */
    public void setDhCont(Date dataHoraContigencia) {
        setDataHoraContigencia(dataHoraContigencia);
    }

    /**
     * Justificativa da Entrada em Contingência.
     */
    public String getJustificativa() {
        return justificativa;
    }

    /**
     * Justificativa da Entrada em Contingência.
     */
    public String getXJust() {
        return getJustificativa();
    }

    /**
     * Informar a justificatica da entrada em contingência.
     * @param justificativa Justificativa da Entrada em Contingência
     */
    public void setJustificativa(String justificativa) {
        this.justificativa = justificativa;
    }

    /**
     * Informar a justificatica da entrada em contingência.
     * @param justificativa Justificativa da Entrada em Contingência
     */
    public void setXJust(String justificativa) {
        setJustificativa(justificativa);
    }

    /**
     * Cliente/Destinatário da NF-e.
     */
    public ClienteTO getClienteTO() {
        return clienteTO;
    }

    /**
     * Informar o cliente/destinatário da NF-e.
     * @param clienteTO Cliente/Destinatário da NF-e
     */
    public void setClienteTO(ClienteTO clienteTO) {
        this.clienteTO = clienteTO;
    }

    /**
     * Lista de Produtos da NF-e.
     */
    public List<ProdutoNotaTO> getListaProdutos() {
        return listaProdutos;
    }

    /**
     * Informar a lista de itens de produtos/serviços da NF-e.
     * @param listaProdutos Lista de Produtos da NF-e
     */
    public void setListaProdutos(List<ProdutoNotaTO> listaProdutos) {
        this.listaProdutos = listaProdutos;
    }

    /**
     * Transporte da NF-e.
     */
    public TransporteTO getTransporteTO() {
        return transporteTO;
    }

    /**
     * Informar o transporte da NF-e.
     * @param transporteTO Transporte da NF-e
     */
    public void setTransporteTO(TransporteTO transporteTO) {
        this.transporteTO = transporteTO;
    }

    /**
     * Informações Adicionais da NF-e.
     */
    public InfoTO getInfoTO() {
        return infoTO;
    }

    /**
     * Preencher com a classe de informações adidionais da NF-e.
     * @param infoTO Informações Adicionais da NF-e
     */
    public void setInfoTO(InfoTO infoTO) {
        this.infoTO = infoTO;
    }

    /**
     * Situação atual da NF-e.
     */
    public SituacaoNFeEnum getSituacao() {
        return situacao;
    }

    /**
     * Informar a situação atual da NF-e.
     * @param situacao Situação atual da NF-e
     */
    public void setSituacao(SituacaoNFeEnum situacao) {
        this.situacao = situacao;
    }

    /**
     * Local de Retirada.
     */
    public LocalTO getRetirada() {
        return retirada;
    }

    /**
     * Informar o local de retirada.
     * <p><b>Informar apenas quando for diferente do endereço do remetente.</b></p>
     * @param retirada Local de Retirada
     */
    public void setRetirada(LocalTO retirada) {
        this.retirada = retirada;
    }

    /**
     * Local de Entrega.
     */
    public LocalTO getEntrega() {
        return entrega;
    }

    /**
     * Informar o local de entrega.
     * <p><b>Informar apenas quando for diferente do endereço do destinatário.</b></p>
     * @param entrega Local de Entrega
     */
    public void setEntrega(LocalTO entrega) {
        this.entrega = entrega;
    }

    /**
     * Código de erro do retorno.
     */
    public String getCodigoErro() {
        return codigoErro;
    }

    /**
     * Informar o código de erro do retorno.
     * @param codigoErro Código de erro do retorno
     */
    public void setCodigoErro(String codigoErro) {
        this.codigoErro = codigoErro;
    }

    /**
     * Mensagem de erro.
     */
    public String getMensagemErro() {
        return mensagemErro;
    }

    /**
     * Informmar a mensagem de erro.
     * @param mensagemErro Mensagem de erro
     */
    public void setMensagemErro(String mensagemErro) {
        this.mensagemErro = mensagemErro;
    }
}
